using System;
using System.Collections.Generic;
using Oracle.ManagedDataAccess.Client;
using OracleInternal.Common;
using OracleInternal.Network;
using OracleInternal.ServiceObjects;

namespace OracleInternal.TTC
{
	internal class TTCDirectPathPrepare : TTCFunction
	{
		private const short ODPP = 128;

		private const byte DPPOPC_LOAD = 1;

		private const byte DPPOPC_UNLOAD = 2;

		private const byte DPPOPC_CONVERT = 3;

		private const int DPPDEF_IN_IVRSN = 0;

		private const long INTERFACE_VERSION = 400L;

		private const int DPPDEF_KW_OBJ_NAME = 1;

		private const int DPPDEF_KW_SUB_NAME = 2;

		private const int DPPDEF_KW_SCHEMA_NAME = 3;

		private const int DPPDEF_KW_COLUMN_NAME = 4;

		private const int DPPDEF_KW_SORTED_INDEX = 5;

		private const int DPPDEF_KW_PARALLEL_FILE = 6;

		private const int DPPDEF_KW_ADTATTR_NAME = 7;

		private const int DPPDEF_KW_ADTATTR_EXPR = 8;

		private const int DPPDEF_KW_ADTATTR_OBJ_CNT = 9;

		private const int DPPDEF_KW_ADTATTR_OPQ_CNT = 10;

		private const int DPPDEF_KW_ADTATTR_REF_CNT = 11;

		private const int DPPDEF_KW_ADTATTR_TYPE = 12;

		private const int DPPDEF_KW_METADATA = 13;

		private const int DPPDEF_KW_UNLOAD_SCN_BASE = 14;

		private const int DPPDEF_KW_UNLOAD_SCN_WRAP = 15;

		private const int DPPDEF_KW_GRANULE_SIZE = 16;

		private const int DPPDEF_KW_SERVER_ROWS = 17;

		private const int DPPDEF_KW_COMMIT_EXPR = 18;

		private const int DPPDEF_KW_ADTATTR_EXPR_CNT = 19;

		private const int DPPDEF_KW_SUBTYPE_BITVECTORS = 20;

		private const int DPPDEF_KW_SUBTYPE_INDEX = 21;

		private const int DPPDEF_KW_SERVER_SLOT_SIZE = 22;

		private const int DPPDEF_KW_DROPCOL_BITVECTOR = 23;

		private const int DPPDEF_IN_STRVRSN = 1;

		private const long STREAM_VERSION = 400L;

		private const int DPPDEF_IN_XFRSIZE = 2;

		private const int DPPDEF_IN_NOLOG = 3;

		private const int DPPDEF_IN_PARALLEL = 4;

		private const int DPPDEF_IN_SKIP_UNUSABLE_INDEX = 5;

		private const int DPPDEF_IN_SKIP_INDEX_MAINT = 6;

		private const int DPPDEF_IN_SINGLE_ROW_INDEX = 7;

		private const int DPPDEF_IN_STORAGE_INIT = 8;

		private const int DPPDEF_IN_STORAGE_NEXT = 9;

		private const int DPPDEF_IN_NESTED_TBL = 10;

		private const int DPPDEF_IN_NFOBJTBL_OIDPOS = 11;

		private const int DPPDEF_IN_SUBST_OBJTBL = 12;

		private const int DPPDEF_IN_DONT_SKIP_UNUSABLE_INDEX = 13;

		private const int DPPDEF_IN_LOCK_WAIT = 14;

		private const int DPPDEF_IN_VARRAY_TBL = 15;

		private const int DPPDEF_IN_NFOBJTBL_SIDPOS = 16;

		private const int DPPDEF_IN_NFOBJTBL_VAIPOS = 17;

		private const int DPPDEF_IN_PARTCONOPT = 18;

		private const int DPPDEF_IN_INTPARTUSED = 19;

		private const int DPPDEF_IN_INTSUBPARTUSED = 20;

		private const int DPPDEF_IN_RTNLEAVECASE = 21;

		private const int DPPDEF_IN_PARALLEL_LOB_LOAD = 22;

		private const int DPPDEF_IN_NO_INDEX_ERRORS = 23;

		private const int DPPDEF_IN_PARTITION_MEMORY = 24;

		private const int DPPDEF_IN_TABLE_PREEXISTS = 25;

		private const int DPPDEF_IN_USE_ACTIVE_TRANS = 26;

		private const int DPPDEF_IN_LONG_VARCHAR = 27;

		private const int DPPDEF_IN_ISLDRCLIENT = 28;

		private const int DPPDEF_IN_COLSEGCOL_LOBORDER = 29;

		private const int DPPDEF_IN_INTCOL_LOBORDER = 30;

		private const int DPPDEF_IN_COMPRESS_UNLOAD_BUFFS = 31;

		private const int DPPDEF_IN_DPFLAGS = 32;

		private const int DPPDEF_IN_DEFAULTS = 33;

		private const int DPPDEF_IN_DEFAULT_EXPR_CACHE_SIZE = 34;

		private const int DPPDEF_IN_CONTINUE_ON_ERRORS = 35;

		private const int DPPDEF_IN_USE_PENDING_TRANS = 36;

		private const int DPPDEF_IN_PARMCOUNT = 37;

		private const int DPPDEF_OUT_IVRSN = 0;

		private const int DPPDEF_OUT_STRVRSN = 1;

		private const int DPPDEF_OUT_XFRSIZE = 2;

		private const int DPPDEF_OUT_RETCURSOR = 3;

		private const int DPPDEF_OUT_SDBA_SAME = 4;

		private const int DPPDEF_OUT_SDBAOFBITS = 5;

		private const int DPPDEF_OUT_SDBANFBITS = 6;

		private const int DPPDEF_OUT_SDBABITS = 7;

		private const int DPPDEF_OUT_DBABBITS = 8;

		private const int DPPDEF_OUT_DBAFNEW = 9;

		private const int DPPDEF_OUT_DBAFOLD = 10;

		private const int DPPDEF_OUT_RTNLEAVECASE = 11;

		private const int DPPDEF_OUT_IN_WORKER_PROCESS = 12;

		private const int DPPDEF_OUT_LONG_VARCHAR = 13;

		private const int DPPDEF_OUT_PARMCOUNT = 14;

		internal string m_schemaName = string.Empty;

		internal string m_tableName = string.Empty;

		internal string m_partitionName = string.Empty;

		internal string[] m_columnNames;

		private List<TTCKeywordValuePair> m_dppiparm;

		private long[] m_dppi4;

		private int m_dppi4l;

		private TTCKeywordValuePair[] m_dppoparm;

		private long[] m_dppo4;

		internal TTCDirectPathPrepare(MarshallingEngine mEngine, bool bInTxn)
			: base(mEngine, 128, 0)
		{
			m_dppiparm = new List<TTCKeywordValuePair>();
			m_dppi4 = new long[37];
			m_dppi4[11] = 65535L;
			m_dppi4[16] = 65535L;
			m_dppi4[17] = 65535L;
			setI4Value(0, 400L);
			setI4Value(1, 400L);
			setI4Value(14, 0L);
			if (bInTxn)
			{
				setI4Value(36, 1L);
			}
		}

		private void setI4Value(int key, long value)
		{
			m_dppi4[key] = value;
			m_dppi4l = Math.Max(m_dppi4l, key + 1);
		}

		internal void Init(string schemaName, string tableName, string partitionName, string[] columnNames)
		{
			m_schemaName = schemaName;
			m_tableName = tableName;
			m_partitionName = partitionName;
			m_columnNames = columnNames;
			m_dppiparm.Clear();
			if (!string.IsNullOrEmpty(m_schemaName))
			{
				m_dppiparm.Add(new TTCKeywordValuePair(3, m_schemaName, null));
			}
			if (!string.IsNullOrEmpty(m_tableName))
			{
				m_dppiparm.Add(new TTCKeywordValuePair(1, m_tableName, null));
			}
			if (!string.IsNullOrEmpty(m_partitionName))
			{
				m_dppiparm.Add(new TTCKeywordValuePair(2, m_partitionName, null));
			}
			if (m_columnNames != null)
			{
				for (int i = 0; i < m_columnNames.Length; i++)
				{
					m_dppiparm.Add(new TTCKeywordValuePair(4, m_columnNames[i], null));
				}
			}
		}

		internal void WriteMessage()
		{
			WriteFunctionHeader();
			m_marshallingEngine.MarshalUB4(1L);
			if (m_dppiparm.Count > 0)
			{
				m_marshallingEngine.MarshalPointer();
			}
			else
			{
				m_marshallingEngine.MarshalNullPointer();
			}
			m_marshallingEngine.MarshalSWORD(m_dppiparm.Count);
			if (m_dppi4l > 0)
			{
				m_marshallingEngine.MarshalPointer();
			}
			else
			{
				m_marshallingEngine.MarshalNullPointer();
			}
			m_marshallingEngine.MarshalUWORD(m_dppi4l);
			m_marshallingEngine.MarshalPointer();
			m_marshallingEngine.MarshalPointer();
			m_marshallingEngine.MarshalPointer();
			m_marshallingEngine.MarshalPointer();
			m_marshallingEngine.MarshalPointer();
			m_marshallingEngine.MarshalPointer();
			foreach (TTCKeywordValuePair item in m_dppiparm)
			{
				item.Marshal(m_marshallingEngine);
			}
			for (int i = 0; i < m_dppi4l; i++)
			{
				m_marshallingEngine.MarshalUB4(m_dppi4[i]);
			}
		}

		internal void ReadResponse(out DirectPathContext directPathContext)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)131328, OracleTraceClassName.TTCTransactionEN, OracleTraceFuncName.ReadResponse);
			}
			bool flag = false;
			byte b = 0;
			directPathContext = new DirectPathContext();
			try
			{
				m_marshallingEngine.TTCErrorObject.Initialize();
				while (!flag)
				{
					try
					{
						switch (m_marshallingEngine.UnmarshalSB1())
						{
						case 23:
							ProcessServerSidePiggybackFunction(0);
							break;
						case 8:
							Process_RPA_Message(ref directPathContext);
							break;
						case 15:
							m_marshallingEngine.TTCErrorObject.ReadWarning();
							break;
						case 4:
							flag = true;
							m_marshallingEngine.TTCErrorObject.ReadErrorMessage();
							if (m_marshallingEngine.TTCErrorObject.ErrorCode == 1403)
							{
								m_marshallingEngine.TTCErrorObject.Initialize();
							}
							else
							{
								OracleConnectionImpl.CheckForAnyErrorFromDB(m_marshallingEngine.TTCErrorObject);
							}
							break;
						case 9:
							if (m_marshallingEngine.HasEOCSCapability)
							{
								m_marshallingEngine.m_endOfCallStatus = m_marshallingEngine.UnmarshalUB4();
							}
							flag = true;
							break;
						default:
							throw new Exception("TTC error");
						}
					}
					catch (NetworkException ex)
					{
						if (ex.ErrorCode != 3111)
						{
							throw;
						}
						m_marshallingEngine.m_oracleCommunication.Reset();
					}
					catch (Exception)
					{
						if (m_marshallingEngine.m_oraBufRdr != null)
						{
							m_marshallingEngine.m_oraBufRdr.ClearState();
						}
						if (!flag)
						{
							m_marshallingEngine.m_oracleCommunication.Break();
							m_marshallingEngine.m_oracleCommunication.Reset();
							continue;
						}
						throw;
					}
				}
			}
			catch (Exception ex3)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268566528, OracleTraceClassName.TTCTransactionEN, OracleTraceFuncName.ReadResponse, ex3);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)131584, OracleTraceClassName.TTCTransactionEN, OracleTraceFuncName.ReadResponse);
				}
			}
		}

		internal void Prepare(out DirectPathContext dpContext)
		{
			WriteMessage();
			ReadResponse(out dpContext);
		}

		private void Process_RPA_Message(ref DirectPathContext directPathContext)
		{
			int num = m_marshallingEngine.UnmarshalUB2();
			directPathContext.m_columnsMetaData = null;
			if (num > 0)
			{
				ColumnDescribeInfo[] array = new ColumnDescribeInfo[num];
				for (int i = 0; i < num; i++)
				{
					array[i] = new ColumnDescribeInfo();
					TTCColumnInfo.ReadMessage(m_marshallingEngine, array[i], bIgnoreMetadata: false);
				}
				directPathContext.m_columnsMetaData = new ColumnDescribeInfo[m_columnNames.Length];
				int num2 = 0;
				bool flag = false;
				for (int j = 0; j < array.Length; j++)
				{
					int num3 = 0;
					while (j < m_columnNames.Length)
					{
						if (array[j].pColAlias == m_columnNames[num3])
						{
							flag = true;
							break;
						}
						num3++;
					}
					if (flag)
					{
						directPathContext.m_columnsMetaData[num2++] = array[j];
						flag = false;
					}
				}
			}
			int num4 = m_marshallingEngine.UnmarshalUB2();
			m_dppoparm = new TTCKeywordValuePair[num4];
			for (int k = 0; k < num4; k++)
			{
				m_dppoparm[k] = TTCKeywordValuePair.Unmarshal(m_marshallingEngine);
			}
			int num5 = m_marshallingEngine.UnmarshalUB2();
			m_dppo4 = new long[num5];
			for (int l = 0; l < num5; l++)
			{
				m_dppo4[l] = m_marshallingEngine.UnmarshalUB4();
			}
			PopulateDPContext(ref directPathContext);
		}

		private long getO4Value(int key)
		{
			if (m_dppo4 == null || m_dppo4.Length <= key)
			{
				return 0L;
			}
			return m_dppo4[key];
		}

		internal void PopulateDPContext(ref DirectPathContext DPContext)
		{
			DPContext.m_tableCursor = getO4Value(3);
			DPContext.m_sDBAOfBits = getO4Value(5);
			DPContext.m_sDBABits = getO4Value(5);
			DPContext.m_DBABits = getO4Value(8);
		}
	}
}
